#include <iostream>
#include <fstream>
#include "baseline.h"

using namespace std;

// constructor
Baseline::Baseline(list<Structures::process> p){
	processes = p;

	Structures::processor p1('A', 8388608, 2000);
	Structures::processor p2('B', 8388608, 2000);
	Structures::processor p3('C', 8388608, 2000);
	Structures::processor p4('D', 8388608, 2000);
	Structures::processor p5('E', 8388608, 2000);

	p1.timeLeft = 0; p1.cyclesRemaining = 0;
	p2.timeLeft = 0; p2.cyclesRemaining = 0;
	p3.timeLeft = 0; p3.cyclesRemaining = 0;
	p4.timeLeft = 0; p4.cyclesRemaining = 0;
	p5.timeLeft = 0; p5.cyclesRemaining = 0;

	processors.push_back(p1);
	processors.push_back(p2);
	processors.push_back(p3);
	processors.push_back(p4);
	processors.push_back(p5);
}

// generate and schedule processes
void Baseline::schedule(){
	
	while(processes.size() != 0){

		// cycle through processors while processes are left
		for(list<Structures::processor>::iterator j = processors.begin(); j != processors.end(); j++)
		{
			// get next process
			list<Structures::process>::iterator i = processes.begin();
			Structures::process minProcess = (*i);
			processes.pop_front();

			(*j).processes.push_back(minProcess);
			(*j).cyclesRemaining += minProcess.burst;
		}

	}
}

// print list
void Baseline::print(){
	ofstream outfile;
	outfile.open ("baseline_output.txt");

	outfile << "Baseline: Identical processors, FIFO scheduling" << endl << endl;

	processors.sort(Structures::compareProcessorID);
	// print out scheduled processes for each processor
	for(int i = 0; i < 5; i++){
		
		outfile << "Processor " << (*processors.begin()).processorid << endl;
		outfile << "\tPID:\tBurst (x1,000,000):\tMemory (in KB):" << endl;
		outfile << "----------------------------------------------------------" << endl;

		int num = 1;
		double totalTime = 0.0;
		double waitTime = 0.0;
		
		for(list<Structures::process>::iterator i = (*processors.begin()).processes.begin(); i != (*processors.begin()).processes.end(); i++)
		{
			outfile << num << ".\t" << (*i).pid << "\t" << (*i).burst;
			num++;
			if((*i).burst < 10000000) //extra tab for shorter numbers
			{
				outfile << "\t";
			}
			outfile	<< "\t\t" << (*i).memoryReq << endl;
			//metrics
			totalTime += (*i).burst / (double)(*processors.begin()).speed;
			waitTime += totalTime;
		}
		waitTime -= totalTime; // remove the last process's time
		num--; // undo the last increment, use this as num of processes

		outfile << "Total cycles scheduled: " << (*processors.begin()).cyclesRemaining << " (x1,000,000)" << endl;
		outfile << "Time required: " << totalTime << " (in seconds)" << endl;

		// Avg wait time: divide the summation of waiting times by num
		outfile << "Avg. wait time: " << waitTime / (double)num  << " (in seconds)" << endl << endl;
		processors.pop_front();
	}

	outfile.close();
}
